package info.fastpace.utils.iterator;

import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
/**
 * The class iterates over sub-elements (SubE) and combines similar into a new element - E
 * 
 * @author alik
 *
 * @param <E>
 * @param <SubE>
 */
public abstract class CombineIterator<E, SubE> implements Iterator<E> {

	private Iterator<SubE> subIterator;
	private Comparator<SubE> comparator;
	private E next;
	private SubE waiting;

	public CombineIterator(Iterator<SubE> subIterator) {
		this.subIterator = subIterator;
		comparator = createComparator();
	}

	protected abstract Comparator<SubE> createComparator();

	protected abstract E combine(List<SubE> combinedElements);

	@Override
	public boolean hasNext() {
		if (next == null) {
			List<SubE> combinedElements = new LinkedList<SubE>();
			if (waiting != null) {
				combinedElements.add(waiting);
				waiting = null;
			}
			while (subIterator.hasNext()) {
				waiting = subIterator.next();

				if (combinedElements.isEmpty() || comparator.compare(combinedElements.get(0), waiting) == 0) {
					combinedElements.add(waiting);
					waiting = null;
				}else {
					// Found different sub-element which should not be combined
					break;
				}
			}
			if (!combinedElements.isEmpty()) {
				next = combine(combinedElements);
			}
		}

		return next != null;
	}

	@Override
	public E next() {
		if (!hasNext()) {
			throw new NoSuchElementException("No more elements");
		}
		E next = this.next;
		this.next = null;

		return next;
	}

	@Override
	public void remove() {
		throw new UnsupportedOperationException("Remove method not supported");
	}

}
